package cn.fntop.config;

import cn.fntop.utils.JansiUtil;
import cn.hutool.core.lang.ObjectId;
import cn.hutool.core.util.StrUtil;
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.fusesource.jansi.Ansi;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * spy SQL美化实现
 */
@Slf4j
public class SpySqlFormatConfigure implements MessageFormattingStrategy {

    /**
     * <p>输出执行sql信息</p >
     *
     * @param connectionId
     * @param now          执行时间
     * @param elapsed      耗时多少毫秒
     * @param category
     * @param prepared     准备执行的sql脚本
     * @param sql          执行的sql脚本
     * @param url          数据源连接地址
     * @author
     * @date 2021/12/3
     */
    @Override
    @SneakyThrows
    public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) {
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.submit(() -> {
            synchronized (ObjectId.next()) {
                if (log.isInfoEnabled() && StringUtils.isNotBlank(sql)) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(sql.getBytes(StandardCharsets.UTF_8))));
                    String line;
                    StringBuilder resultSQL = new StringBuilder();
                    try {
                        while ((line = reader.readLine()) != null) {
                            if (StringUtils.isBlank(StrUtil.cleanBlank(line))) {
                                continue;
                            }
                            resultSQL.append("\n").append(line);
                        }
                    } catch (Exception e) {
                    }
                    String timeStr;
                    //方便找到需要优化的SQL
                    if (elapsed / 1000 > 10) {
                        //大于十秒，异常SQL
                        timeStr = JansiUtil.applyColor(Ansi.Color.RED, "RED:" + elapsed);
                    } else if (elapsed / 1000 < 3) {
                        //小于3秒，正常SQL
                        timeStr = JansiUtil.applyColor(Ansi.Color.GREEN, "GREEN:" + elapsed);
                    } else if (elapsed / 1000 > 3 && elapsed / 1000 <= 10) {
                        //警告SQL
                        timeStr = JansiUtil.applyColor(Ansi.Color.YELLOW, "YELLOW:" + elapsed);
                    } else {
                        //SQL错乱时会不标错
                        timeStr = JansiUtil.applyColor(Ansi.Color.CYAN, "CYAN:" + elapsed);

                    }
                    log.info("\n耗时 [{}ms]，执行时间 [{}]，执行SQL如下 => {}", timeStr, now, resultSQL);
                }
            }
        });
        try {
            //先停止接收任务，然后再等待一定的时间让所有的任务都执行完毕，如果超过了给定的时间，则立刻结束任务。
            executor.shutdown();
            if (!executor.awaitTermination(800, TimeUnit.MILLISECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
        }
        return "";

    }
}
